package com.codedancer.campus.manager.service.impl;


import cn.afterturn.easypoi.entity.vo.NormalExcelConstants;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.UUIDGenerator;
import com.codedancer.campus.enums.CommodityStatus;
import com.codedancer.campus.enums.SystemMessageType;
import com.codedancer.campus.manager.mq.producer.MqSendMessageProducer;
import com.codedancer.campus.manager.service.ICommodityService;
import com.codedancer.campus.manager.service.bo.commodity.CommodityExamineBo;
import com.codedancer.campus.manager.service.bo.commodity.CommodityPageSearchBo;
import com.codedancer.campus.manager.service.excel.CommodityExcel;
import com.codedancer.campus.manager.service.model.SystemMessageMqParamModel;
import com.codedancer.campus.manager.service.vo.commodity.CommodityPageVo;
import com.codedancer.campus.manager.service.vo.commodity.CommodityVo;
import com.codedancer.campus.mapper.CommodityExamineRecordMapper;
import com.codedancer.campus.mapper.CommodityImageMapper;
import com.codedancer.campus.mapper.CommodityMapper;
import com.codedancer.campus.mapper.UserMapper;
import com.codedancer.campus.po.Commodity;
import com.codedancer.campus.po.CommodityExamineRecord;
import com.codedancer.campus.po.CommodityImage;
import com.codedancer.campus.po.User;
import com.codedancer.campus.qo.commodity.CommodityPageSearchQo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class CommodityServiceImpl implements ICommodityService {

    @Autowired
    private CommodityMapper commodityMapper;
    @Autowired
    private CommodityImageMapper commodityImageMapper;
    @Autowired
    private CommodityExamineRecordMapper commodityExamineRecordMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private MqSendMessageProducer mqSendMessageProducer;


    /**
     * 分页查询商品
     *
     * @param commodityPageSearchBo
     * @return
     */
    @Override
    public IPage<CommodityPageVo> page(CommodityPageSearchBo commodityPageSearchBo) {
        CommodityPageSearchQo commodityPageSearchQo = BeanUtil.copyProperties(commodityPageSearchBo,
            CommodityPageSearchQo.class);
        IPage<Commodity> commodityIPage = commodityMapper.pageToManager(
            new Page<Commodity>(commodityPageSearchBo.getPage(), commodityPageSearchBo.getSize()),
            commodityPageSearchQo);
        IPage<CommodityPageVo> commodityPageVoIPage = new Page<>();
        List<CommodityPageVo> commodityPageVos;
        commodityPageVos = commodityIPage.getRecords().stream().map(commodity -> {
            CommodityPageVo commodityPageVo = BeanUtil.copyProperties(commodity,
                CommodityPageVo.class);
            commodityPageVo.setPublishNickName(commodity.getPublishUser().getNickName());
            commodityPageVo.setPublishSchoolName(commodity.getPublishSchool().getName());
            commodityPageVo.setCategoryName(commodity.getCategory().getName());
            return commodityPageVo;
        }).collect(Collectors.toList());
        commodityPageVoIPage.setRecords(commodityPageVos);
        commodityPageVoIPage.setTotal(commodityIPage.getTotal());
        return commodityPageVoIPage;
    }

    /**
     * 下架
     *
     * @param uuid
     */
    @Override
    public void drop(String uuid) {
        Commodity commodity = commodityMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("商品不存在"));
        commodity.setStatus(CommodityStatus.OFF_SHELF);
        commodity.setIsAdminOff(true);
        commodityMapper.updateById(commodity);
        SystemMessageMqParamModel systemMessageMqParamModel = SystemMessageMqParamModel.builder()
            .receiveUserUuid(commodity.getPublishUserUuid())
            .messageType(SystemMessageType.COMMODITY_OFF)
            .content("你的商品【" + commodity.getTitle() + "】已被管理员下架，如需上架，请联系管理员")
            .build();
        mqSendMessageProducer.sendSystemMessage(JSONUtil.toJsonStr(systemMessageMqParamModel));
    }

    /**
     * 上架
     *
     * @param uuid
     */
    @Override
    public void put(String uuid) {
        Commodity commodity = commodityMapper.findById(uuid)
            .orElseThrow(() -> new BusinessException("商品不存在"));
        commodity.setStatus(CommodityStatus.ON_SHELF);
        commodity.setIsAdminOff(false);
        commodityMapper.updateById(commodity);
    }

    /**
     * 删除
     *
     * @param uuid
     */
    @Override
    public void delete(String uuid) {
        if (!commodityMapper.existsByUuId(uuid)) {
            throw new BusinessException("商品不存在");
        }
        commodityMapper.deleteById(uuid);
    }

    /**
     * 商品详情
     *
     * @param uuid
     * @return
     */
    @Override
    public CommodityVo detail(String uuid) {
        Commodity commodity = commodityMapper.detail(uuid);
        CommodityVo commodityVo = BeanUtil.copyProperties(commodity, CommodityVo.class);
        commodityVo.setCategoryName(commodity.getCategory().getName());
        commodityVo.setPublishNickName(commodity.getPublishUser().getNickName());
        commodityVo.setPublishSchoolName(commodity.getPublishSchool().getName());
        // 获取商品图片
        List<CommodityImage> commodityImages = commodityImageMapper.selectListByColumn(
            "commodity_uuid", uuid);
        commodityVo.setImages(commodityImages.stream().map(CommodityImage::getImageUrl).collect(
            Collectors.toList()));
        // 查询最近一条审核记录
        CommodityExamineRecord commodityExamineRecord = commodityExamineRecordMapper
            .selectLastExamineRecord(uuid);
        if (ObjectUtil.isNotEmpty(commodityExamineRecord) && !commodityExamineRecord.getIsPass()) {
            commodityVo.setLastNoPassReason(commodityExamineRecord.getNoPassReason());
        }
        return commodityVo;
    }

    /**
     * 审核未通过
     *
     * @param commodityExamineBo
     */
    @Override
    public void noPass(CommodityExamineBo commodityExamineBo) {
        Commodity commodity = commodityMapper.findById(commodityExamineBo.getUuid())
            .orElseThrow(() -> new BusinessException("商品不存在"));
        if (ObjectUtil.isEmpty(commodityExamineBo.getNoPassReason())) {
            throw new BusinessException("请输入原因");
        }
        // 判断是否审核次数大于5
        if (commodity.getExamineCount() > 5) {
            throw new BusinessException("审核次数已超过上限5次");
        }
        commodity.setStatus(CommodityStatus.NOT_PASS);
        // 审核次数加1
        commodity.setExamineCount(commodity.getExamineCount() + 1);
        commodityMapper.updateById(commodity);
        // 保存审核记录信息
        CommodityExamineRecord commodityExamineRecord = CommodityExamineRecord.builder()
            .uuid(UUIDGenerator.getUUID())
            .commodityUuid(commodity.getUuid())
            .isPass(false)
            .examineAdminUuid(commodityExamineBo.getCurrentUserUuid())
            .noPassReason(commodityExamineBo.getNoPassReason())
            .build();
        commodityExamineRecordMapper.insert(commodityExamineRecord);
        // 将消息投递到消息队列中
        SystemMessageMqParamModel systemMessageMqParamModel = SystemMessageMqParamModel.builder()
            .messageType(SystemMessageType.COMMODITY_EXAMINE)
            .content("【" + commodity.getTitle() + "】未审核通过，原因为:" + commodityExamineBo
                .getNoPassReason())
            .receiveUserUuid(commodity.getPublishUserUuid())
            .build();
        mqSendMessageProducer.sendSystemMessage(JSONUtil.toJsonStr(systemMessageMqParamModel));
    }

    /**
     * 审核通过
     *
     * @param commodityExamineBo
     */
    @Override
    public void pass(CommodityExamineBo commodityExamineBo) {
        Commodity commodity = commodityMapper.findById(commodityExamineBo.getUuid())
            .orElseThrow(() -> new BusinessException("商品不存在"));
        User user = userMapper.selectById(commodity.getPublishUserUuid());
        // 判断是否审核次数大于5
        if (commodity.getExamineCount() > 5) {
            throw new BusinessException("审核次数已超过上限5次");
        }
        commodity.setStatus(CommodityStatus.ON_SHELF);
        // 审核次数加1
        commodity.setExamineCount(commodity.getExamineCount() + 1);
        commodityMapper.updateById(commodity);
        // 保存审核记录信息
        CommodityExamineRecord commodityExamineRecord = CommodityExamineRecord.builder()
            .uuid(UUIDGenerator.getUUID())
            .commodityUuid(commodity.getUuid())
            .isPass(true)
            .examineAdminUuid(commodityExamineBo.getCurrentUserUuid())
            .build();
        commodityExamineRecordMapper.insert(commodityExamineRecord);
        // 将消息投递到消息队列中
        SystemMessageMqParamModel systemMessageMqParamModel = SystemMessageMqParamModel.builder()
            .messageType(SystemMessageType.COMMODITY_EXAMINE)
            .content("【" + commodity.getTitle() + "】审核通过")
            .receiveUserUuid(commodity.getPublishUserUuid()).build();
        mqSendMessageProducer.sendSystemMessage(JSONUtil.toJsonStr(systemMessageMqParamModel));
        // 给粉丝推送消息
        // 根据用户uuid获取全部关注者记录
        SystemMessageMqParamModel commodityPublishSystemMessageMqParamModel = SystemMessageMqParamModel.builder()
            .commodityPublishUserUuid(commodity.getPublishUserUuid())
            .messageType(SystemMessageType.COMMODITY_PUBLISH).build();
        mqSendMessageProducer.sendSystemMessage(
            JSONUtil.toJsonStr(commodityPublishSystemMessageMqParamModel));
    }

    /**
     * 导出商品
     *
     * @param response
     */
    @Override
    public void export(HttpServletRequest request, HttpServletResponse response,
        CommodityPageSearchBo commodityPageSearchBo) {
        log.info("开始导出商品数据");
        CommodityPageSearchQo commodityPageSearchQo = BeanUtil
            .copyProperties(commodityPageSearchBo, CommodityPageSearchQo.class);
        // 先获取导出的商品数据
        List<Commodity> commodities = commodityMapper.listExportCommodity(commodityPageSearchQo);
        // 组转数据
        List<CommodityExcel> commodityExcels = assembleData(commodities);
        Map<String, Object> map = new HashMap<>();
        ExportParams params = new ExportParams("商品列表", "商品列表", ExcelType.HSSF);
        map.put(NormalExcelConstants.DATA_LIST, commodityExcels);
        map.put(NormalExcelConstants.CLASS, CommodityExcel.class);
        map.put(NormalExcelConstants.PARAMS, params);
        map.put(NormalExcelConstants.FILE_NAME, "商品列表" + DateUtil.today());
        PoiBaseView.render(map, request, response, NormalExcelConstants.EASYPOI_EXCEL_VIEW);
        log.info("商品导出完成");
    }

    /**
     * 批量下架
     *
     * @param uuids
     */
    @Override
    public void batchDrop(List<String> uuids) {
        for (String uuid : uuids) {
            Commodity commodity = commodityMapper.findById(uuid)
                .orElseThrow(() -> new BusinessException("商品不存在，商品uuid：" + uuid));
            commodity.setIsAdminOff(true);
            commodity.setStatus(CommodityStatus.OFF_SHELF);
            commodityMapper.updateById(commodity);
            SystemMessageMqParamModel systemMessageMqParamModel = SystemMessageMqParamModel.builder()
                .receiveUserUuid(commodity.getPublishUserUuid())
                .messageType(SystemMessageType.COMMODITY_OFF)
                .content("你的商品已被管理员下架，如需上架，请联系管理员").build();
            mqSendMessageProducer.sendSystemMessage(JSONUtil.toJsonStr(systemMessageMqParamModel));
        }
    }

    /**
     * 批量上架
     *
     * @param uuids
     */
    @Override
    public void batchPut(List<String> uuids) {
        for (String uuid : uuids) {
            Commodity commodity = commodityMapper.findById(uuid)
                .orElseThrow(() -> new BusinessException("商品不存在，商品uuid：" + uuid));
            commodity.setIsAdminOff(false);
            commodity.setStatus(CommodityStatus.ON_SHELF);
            commodityMapper.updateById(commodity);
        }
    }

    /**
     * 批量删除
     *
     * @param uuids
     */
    @Override
    public void batchDelete(List<String> uuids) {
        for (String uuid : uuids) {
            if (!commodityMapper.existsByUuId(uuid)) {
                throw new BusinessException("商品不存在，商品uuid：" + uuid);
            }
            commodityMapper.deleteById(uuid);
        }
    }

    /**
     * 组装数据 将commodity转换为communityExportExcel
     *
     * @param commodities
     * @return
     */
    private List<CommodityExcel> assembleData(List<Commodity> commodities) {
        return commodities.stream().map(commodity -> {
            CommodityExcel commodityExcel = BeanUtil
                .copyProperties(commodity, CommodityExcel.class);
            commodityExcel.setCategoryName(commodity.getCategory().getName());
            commodityExcel.setPublishNickName(commodity.getPublishUser().getNickName());
            commodityExcel.setPublishSchoolName(commodity.getPublishSchool().getName());
            commodityExcel.setStatus(commodity.getStatus().getName());
            return commodityExcel;
        }).collect(Collectors.toList());
    }
}
